package com.mtsoft.mfkernel;

import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author Mark.Taylor
 */
public class Util {

    /*
     * IBM and similar mainframe systems (Wang?)
     * Map of display length to binary storage length ie Pic 999 -> 2 bytes
     */
    private static Map<Integer, Integer> IbmBinaryStorageMap = new HashMap<Integer, Integer>();
    static {
        IbmBinaryStorageMap.put(1,2);
        IbmBinaryStorageMap.put(2,2);
        IbmBinaryStorageMap.put(3,2);
        IbmBinaryStorageMap.put(4,2);
        IbmBinaryStorageMap.put(5,4);
        IbmBinaryStorageMap.put(6,4);
        IbmBinaryStorageMap.put(7,4);
        IbmBinaryStorageMap.put(8,4);
        IbmBinaryStorageMap.put(9,4);
        IbmBinaryStorageMap.put(10,8);
        IbmBinaryStorageMap.put(11,8);
        IbmBinaryStorageMap.put(12,8);
        IbmBinaryStorageMap.put(13,8);
        IbmBinaryStorageMap.put(14,8);
        IbmBinaryStorageMap.put(15,8);
        IbmBinaryStorageMap.put(16,8);
        IbmBinaryStorageMap.put(17,8);
        IbmBinaryStorageMap.put(19,8);
    }

    /*
     * Microfocus and similar (OpenCobol, ...)
     * Map of display length to binary storage length ie Pic 999 -> 2 bytes
     */
    private static Map<Integer, Integer> MfBinaryStorageMap = new HashMap<Integer, Integer>();
    static {
        MfBinaryStorageMap.put(1,1);
        MfBinaryStorageMap.put(2,1);
        MfBinaryStorageMap.put(3,2);
        MfBinaryStorageMap.put(4,2);
        MfBinaryStorageMap.put(5,3);
        MfBinaryStorageMap.put(6,3);
        MfBinaryStorageMap.put(7,3);
        MfBinaryStorageMap.put(8,4);
        MfBinaryStorageMap.put(9,4);
        MfBinaryStorageMap.put(10,5);
        MfBinaryStorageMap.put(11,5);
        MfBinaryStorageMap.put(12,5);
        MfBinaryStorageMap.put(13,6);
        MfBinaryStorageMap.put(14,6);
        MfBinaryStorageMap.put(15,7);
        MfBinaryStorageMap.put(16,7);
        MfBinaryStorageMap.put(17,8);
        MfBinaryStorageMap.put(19,8);
    }

    public static int getBinaryStorageLength(int displayLength, boolean ibmComp) {
        int retVal;

        if(displayLength > 18 || displayLength <= 0) {
            retVal = 0;
        }
        if(ibmComp) {
            retVal = IbmBinaryStorageMap.get(displayLength);
        } else {
            retVal = MfBinaryStorageMap.get(displayLength);
        }
        return retVal;
    }
    
    /**
     * Takes a string in UTF-16BE and replaces all control chars
     * with periods '.' for displaying binary data.
     *
     * @param s
     * @return
     */
    public static String replaceCtrlPeriod(String s) {
        char[] buffer = s.toCharArray();
        for(int i = 0; i < buffer.length; i++) {
            char c = buffer[i];
            if(Character.isISOControl(c)) {
                buffer[i] = '.';
            }
        }
        return new String(buffer);
    }

    public static String bytesToString(byte[] bytes, int start, int length) {
        StringBuilder buffer = new StringBuilder();
        if(start > bytes.length) {
            int end = Math.min(start + length, length - start);
            for(int i = start; i < end; i++) {
                String hex = toHexString(bytes[i]);
                buffer.append(hex);
            }
            if(buffer.length() > 0) {
                buffer.deleteCharAt(0);
            }
        }
        return buffer.toString();
    }
    
    public static void printBytes(byte[] bytes) {
        System.out.print("bytes:");
        for(byte b : bytes) {
            System.out.print(toHexString(b));
        }
        System.out.println(":");
    }
    
    public static String toHexString(byte b) {
        int i = toPosByte(b);
        byte b1 = (byte)(i & 0x0f);
        byte b2 = (byte)(i >>> 4);
        return "." + hexMap.get(toPosByte(b2)) + hexMap.get(toPosByte(b1));
    }
    
    public static int toPosByte(byte b) {
        return b & 0xff;
    }
    
    private static Map<Integer, String> hexMap;
    static {
        hexMap = new HashMap<Integer, String>();
        hexMap.put(0, "0");
        hexMap.put(1, "1");
        hexMap.put(2, "2");
        hexMap.put(3, "3");
        hexMap.put(4, "4");
        hexMap.put(5, "5");
        hexMap.put(6, "6");
        hexMap.put(7, "7");
        hexMap.put(8, "8");
        hexMap.put(9, "9");
        hexMap.put(10, "a");
        hexMap.put(11, "b");
        hexMap.put(12, "c");
        hexMap.put(13, "d");
        hexMap.put(14, "e");
        hexMap.put(15, "f");
    }
}
